import { ComponentClass } from 'react'
import Taro, { Component } from '@tarojs/taro'
import { View, Text, Image, Button } from '@tarojs/components'
import { connect } from '@tarojs/redux'

import {
  depositFilterOptions,
  timeFilterOptions,
  sortFilterOptions,
  productTypeOptions,
  mortgageTypeOptions,
  jobsOptions,
} from '../../config';
import SelectOption from '../../model/select-option';
import ProductFilterMenu from '../product-filter-menu';
import ProductFilterSideMenu from '../product-filter-side-menu/';
import Constants from '../../config/constants';
import { Utils } from '../../utils/utils';
import { noConsole } from '../../config'

import './index.scss'

type InputOption = {
  deposit: SelectOption,    // 贷款金额
  time_limit: SelectOption  // 贷款期限选项
  sort: SelectOption,   // 排序选项
  product_type: SelectOption,   // 产品(抵押)类型选项
  mortgage_type: SelectOption,  // 抵押类型选项
  job: SelectOption,   // 职业选项
};

type PageStateProps = {}

type PageDispatchProps = {
  sendConditionAndOption: (type: string, payload: { condition: any, option?: any }) => void
}

type PageOwnProps = {
  // 输入的选项，作为默认选中选项的参数
  inputOption: InputOption,
  // dispatch 的的 type 参数字符串
  dispatchActionType: string,
  // 组件是否需要吸顶，true: 表示组件滚动到顶部时，会自动吸顶
  isNeedFixTop: boolean,
  // 组件所在页面的滚动距离
  scrollTop: number,
  // 组件在Y轴固定定位的坐标
  fixTopY?: number,
}

type PageState = {

  // 贷款过滤选项
  depositFilterOptions: Array<SelectOption>,
  // 贷款额度
  depositDesc: string,
  // 贷款额度菜单是否显示
  isShowDepositMenu: boolean,
  // 贷款额度选项，默认选中第一个
  depositSelectedOption: SelectOption,

  // 贷款期限过滤选项
  timeFilterOptions: Array<SelectOption>,
  // 贷款期限
  timeDesc: string,
  // 贷款期限菜单是否显示
  isShowTimeMenu: boolean,
  // 贷款期限选项，默认选中第一个
  timeSelectedOption: SelectOption,

  // 排序过滤选项
  sortFilterOptions: Array<SelectOption>,
  // 贷款期限菜单是否显示
  isShowSortMenu: boolean,
  // 贷款期限选项，默认选中第一个
  sortSelectedOption: SelectOption,

  // 筛选菜单是否显示
  isShowFilterMenu: boolean,
  // 筛选条件对象
  filter: {
    product_type: SelectOption,
    mortgage_type: SelectOption,
    job: SelectOption,
  },

  // 把各个搜索条件组装成一个对象
  condition: any,

  // 菜单是否显示的标志,只要有一个菜单显示即为true
  isMenuShow: boolean,

  // 过滤条件数量
  filterCount: number,

  // 过滤组件事件的后缀，用作区分
  eventRandom?: string,

  // 产品过滤组件是否要吸顶的标志位, true 表示要吸顶
  isFixTop: boolean,
  // 组件初始化时距离顶部的高度
  yOffsetHeight: number,
}

type IProps = PageStateProps & PageDispatchProps & PageOwnProps

interface ProductFilter {
  props: IProps;
  state: PageState;
}

const utils = new Utils()

/**
 * 产品过滤组件
 */
@connect(({ }) => ({
}), (dispatch) => ({
  sendConditionAndOption(type: string, payload: { condition: any, option?: any }) {
    dispatch({
      type,
      payload,
    })
  },
}))
class ProductFilter extends Component {

  constructor(props) {
    super(props);
    this.state = this._initStateByProps(props);  // 初始化state

    // 初始化事件后缀
    this.state.eventRandom = `_${utils.random(10)}`;

    // 必须放在 eventRandom 初始化后
    this.onDepositOptionChange();

    // 初始化侧边栏监控
    this.onFilterChange();

    // 计算filterCount
    this.updateFilterCount(this.state.filter);
  }

  componentWillReceiveProps(nextProps) {
    const currScrollTop = this.props.scrollTop
    const nextScrollTop = nextProps.scrollTop

    if (currScrollTop != nextScrollTop) {
      this._watchFilterComponentScroll(nextScrollTop)
    }

    // 根据输入的option更新state
    const currInputOption = this.props.inputOption
    const nextInputOption = nextProps.inputOption
    // if (JSON.stringify(nextInputOption) !== JSON.stringify(currInputOption)) {
    if (nextInputOption) {
      // setTimeout(() => {
        const newState = this._getNewSelectionState(nextInputOption)
        this.setState(newState, () => {
          // 计算过滤菜单
          this.updateFilterCount(newState.filter);
        })
      // }, 0)
    }
  }

  componentWillUnmount() {
    this.offDepositOptionChange();
    this.offFilterChange();
  }

  componentDidMount() {
    // console.log('componentDidMount filter component !!!')
    // 必须异步执行，否则计算的h5端高度会有问题
    setTimeout(() => {
      this._setInitOffsetTopHeight()
    }, 200)
  }

  componentDidShow() {
    // console.log('componentDidMount filter component !!!')
    // setTimeout(() => {
    //   this._setInitOffsetTopHeight()
    // }, 200)
  }

  componentDidHide() { }

  render() {
    // const inputOption = this._getInputOptionWithDefaultValue(this.props)
    const { inputOption, fixTopY } = this.props
    const { deposit, time_limit, sort, product_type, mortgage_type, job } = inputOption
    return (
      <View className={`product-filter-container ${this.state.isFixTop ? 'fixed-top' : ''}`} style={(this.state.isFixTop && fixTopY && fixTopY > 0) ? `top: ${fixTopY}px;` : ''}>
        <View className="item" onClick={this.depositOptionTab.bind(this)}>
          <Text className={`text ${this.state.isShowDepositMenu ? 'active' : ''}`}>{deposit.name}</Text>
          <Text className={`iconfont icon-f11 ${!this.state.isShowDepositMenu ? 'down' : 'active'}`}></Text>
        </View>
        <View className="item" onClick={this.timeOptionTab.bind(this)}>
          <Text className={`text ${this.state.isShowTimeMenu ? 'active' : ''}`}>{time_limit.name}</Text>
          <Text className={`iconfont icon-f11 ${!this.state.isShowTimeMenu ? 'down' : 'active'}`}></Text>
        </View>
        <View className="item" onClick={this.sortOptionTab.bind(this)}>
          <Text className={`text ${this.state.isShowSortMenu ? 'active' : ''}`}>{sort.name}</Text>
          <Text className={`iconfont icon-f11 ${!this.state.isShowSortMenu ? 'down' : 'active'}`}></Text>
        </View>
        <View className="item" onClick={this.filterOptionTab.bind(this)}>
          {this.state.filterCount && <Text className="number">{this.state.filterCount}</Text>}
          <Text className={`text ${this.state.filterCount > 0 ? 'active' : ''}`}>筛选</Text>
          <Text className={`iconfont icon-28 icon-filter ${this.state.filterCount > 0 ? 'active' : ''}`}></Text>
        </View >

        <View className={`menu ${this.state.isShowDepositMenu ? '' : 'hide'}`} onClick={this.onAreaTap.bind(this)}>
          <ProductFilterMenu
            allOptions={this.state.depositFilterOptions}
            menuDescription={this.state.depositDesc}
            selectedOption={this.state.depositSelectedOption}
            eventSuffix={this.state.eventRandom}
            type='deposit'>
          </ProductFilterMenu>
        </View>

        <View className={`menu ${this.state.isShowTimeMenu ? '' : 'hide'}`} onClick={this.onAreaTap.bind(this)}>
          <ProductFilterMenu
            allOptions={this.state.timeFilterOptions}
            menuDescription={this.state.timeDesc}
            selectedOption={this.state.timeSelectedOption}
            eventSuffix={this.state.eventRandom}
            type='time'>
          </ProductFilterMenu>
        </View>

        <View className={`menu ${this.state.isShowSortMenu ? '' : 'hide'}`} onClick={this.onAreaTap.bind(this)}>
          <ProductFilterMenu
            allOptions={this.state.sortFilterOptions}
            selectedOption={this.state.sortSelectedOption}
            eventSuffix={this.state.eventRandom}
            type='sort'>
          </ProductFilterMenu>
        </View>

        <ProductFilterSideMenu
          isShow={this.state.isShowFilterMenu}
          selectedProductType={product_type}
          selectedjob={job}
          selectedMrotageType={mortgage_type}
          eventSuffix={this.state.eventRandom}>
        </ProductFilterSideMenu>
      </View >
    )
  }

  /**
   * 初始化产品过滤组件滚动相关参数
   * @param {number} yOffset  y轴滚动距离
   */
  _watchFilterComponentScroll(yOffset: number) {
    // if (!noConsole) {
    //   console.log('_watchFilterComponentScroll, yOffset = ', yOffset)
    // }
    // isNeedFixTop 为true且yOffsetHeight > 0 才继续操作 
    if (this.props.isNeedFixTop && this.state.yOffsetHeight > 0) {

      // yDiff = 组件距离Y轴顶部的高度 - 当前Y轴滑动距离
      let yDiff = this.state.yOffsetHeight - yOffset
      if (this.props.fixTopY) {
        yDiff = yDiff - this.props.fixTopY
      }
      // console.log('yDiff = ', yDiff)
      // yDiff <= 0, 说明已滑动到组件需要吸顶的位置
      if (yDiff < 0) {
        this.setState({
          isFixTop: true,
        })
      } else {
        this.setState({
          isFixTop: false,
        })
      }
    }
  }

  /**
   * 点击菜单时，处理过滤组件的吸顶参数
   * @param scrollTop 页面滚动高度
   * @param yOffsetHeight 组件距离顶部距离
   * @param menuShow 菜单是否显示
   * @param yOffset  组件吸顶位置距离顶部高度
   */
  getIsFixWhileMenuTap(scrollTop: number, yOffsetHeight: number, menuShow: boolean, yOffset: number | undefined): boolean {
    let result = false
    let yDiff = yOffsetHeight - scrollTop
    if (yOffset) {
      yDiff = yDiff - yOffset
    }
    // yDiff <= 0, 说明已滑动到组件需要吸顶的位置

    // 菜单显示的情况下，返回 true
    if (menuShow) {
      result = true
    } else if (!menuShow && yDiff >= 0) {
      // 菜单隐藏的情况下，没有达到滚动距离 设置isFixTop为false
      result = false
    } else if (!menuShow && yDiff < 0) {
      // 菜单隐藏，，设置isFixTop为true
      result = true
    }

    return result
  }

  /**
   * 贷款额度选项点击处理方法
   * @param e 
   */
  depositOptionTab(e) {
    const isShowDepositMenu = !this.state.isShowDepositMenu
    this.setState({
      isShowDepositMenu: isShowDepositMenu,
      isShowSortMenu: false,
      isShowTimeMenu: false,
      isShowFilterMenu: false,
    }, () => {
      this.setMenuOpen();
    });
  }

  /**
   * 排序点击处理方法
   * @param e 
   */
  sortOptionTab(e) {
    const isShowSortMenu = !this.state.isShowSortMenu
    this.setState({
      isShowDepositMenu: false,
      isShowSortMenu: isShowSortMenu,
      isShowTimeMenu: false,
      isShowFilterMenu: false,
    }, () => {
      this.setMenuOpen();
    });
  }

  /**
   * 贷款期限点击处理方法
   * @param e 
   */
  timeOptionTab(e) {
    const isShowTimeMenu = !this.state.isShowTimeMenu
    this.setState({
      isShowDepositMenu: false,
      isShowSortMenu: false,
      isShowTimeMenu: isShowTimeMenu,
      isShowFilterMenu: false,
    }, () => {
      this.setMenuOpen();
    });
  }

  /**
   * 过滤点击处理方法
   */
  filterOptionTab() {
    this.setState({
      isShowFilterMenu: !this.state.isShowFilterMenu,
      isShowSortMenu: false,
      isShowDepositMenu: false,
      isShowTimeMenu: false
    }, () => {
      // 调用 setMenuOpen(), 刷新吸顶状态
      this.setMenuOpen()
    })
  }

  /**
   * 监听贷款额度改变的处理方法
   */
  onDepositOptionChange() {

    Taro.eventCenter.on(`${Constants.FILTER_MENU_SELECT_EVENT}${this.state.eventRandom}`, param => {
      // console.log('onDepositOptionChange param = ', param)
      const { option, type } = param;
      // 点击选项后，更新 depositSelectedOption，关闭菜单
      if (type === 'deposit') {
        this.setState({
          depositSelectedOption: option,
          isShowDepositMenu: false
        }, () => {
          // 发射搜索事件
          this.sendSearchEvent()
          this.setMenuOpen()
        });
      } else if (type === 'time') {
        this.setState({
          timeSelectedOption: option,
          isShowTimeMenu: false
        }, () => {
          // 发射搜索事件
          this.sendSearchEvent()
          this.setMenuOpen()
        });
      } else if (type === 'sort') {
        this.setState({
          sortSelectedOption: option,
          isShowSortMenu: false
        }, () => {
          // 发射搜索事件
          this.sendSearchEvent()
          this.setMenuOpen()
        });
      }
    })
  }

  /**
   * 取消监听额度改变
   */
  offDepositOptionChange() {
    Taro.eventCenter.off(`${Constants.FILTER_MENU_SELECT_EVENT}${this.state.eventRandom}`);
  }

  /**
   * 过滤条件改变的处理方法
   */
  onFilterChange() {
    Taro.eventCenter.on(`${Constants.FILTER_SIDE_MENU_SELECT_EVENT}${this.state.eventRandom}`, param => {

      // console.log('onFilterChange param = ', param)

      const { selectedProductType, selectedjob, selectedMrotageType, isShow } = param;

      // 更新过滤条件
      const update = {
        product_type: selectedProductType || this.state.filter.product_type,
        mortgage_type: selectedMrotageType || this.state.filter.mortgage_type,
        job: selectedjob || this.state.filter.job,
      };
      this.setState({
        filter: update,
      }, () => {
        // 发射搜索事件
        this.sendSearchEvent()
      });
      this.setFilterMenuOpen(isShow);

      // 计算filterCount
      this.updateFilterCount(update);
    })
  }

  /**
   * 停止监听过滤条件改变的处理方法
   */
  offFilterChange() {
    Taro.eventCenter.off(`${Constants.FILTER_SIDE_MENU_SELECT_EVENT}${this.state.eventRandom}`);
  }

  /**
   * 更新filterCount
   * @param filter 过滤条件对象
   */
  updateFilterCount(filter) {
    // 计算过滤条件数量
    let filterCount = 0;

    for (const key in filter) {
      if (filter.hasOwnProperty(key)) {
        const element = filter[key]
        if (element.value) {
          filterCount++
        }
      }
    }

    this.setState({
      filterCount,
    })
  }

  /**
   * 处理过滤侧边栏菜单的显示与隐藏
   * @param {*} isShow
   */
  setFilterMenuOpen(isShow) {
    this.setState({
      isShowFilterMenu: isShow,
    })
  }

  /**
   * 菜单区域点击处理方法
   * @param {*} e 
   */
  onAreaTap(e?) {
    // 设置所有菜单关闭
    this.setState({
      isShowDepositMenu: false,
      isShowTimeMenu: false,
      isShowSortMenu: false,
    }, () => {
      this.setMenuOpen();
    });
  }

  /**
   * 监听过滤菜单的开启,
   * 并设置 isMenuShow,
   * 只要有其中一个菜单开启， isMenuShow为true
   * @param {*} e 
   */
  setMenuOpen(e?) {
    const isShow = this.state.isShowDepositMenu || this.state.isShowTimeMenu || this.state.isShowSortMenu
    this.setState({
      isMenuShow: isShow,
    })

    if (this.props.isNeedFixTop) {
      const isFixTop = this.getIsFixWhileMenuTap(this.props.scrollTop, this.state.yOffsetHeight, isShow, this.props.fixTopY)
      this.setState({
        isFixTop
      })
    }
  }

  /**
   * 获取带默认值的输入选项
   */
  _getInputOptionWithDefaultValue(props: PageOwnProps): InputOption {
    const { inputOption } = props;

    if (inputOption) {
      const deposit: any = inputOption['deposit'] || depositFilterOptions[0]
      const time_limit: any = inputOption.time_limit || timeFilterOptions[0]
      const sort: any = inputOption.sort || sortFilterOptions[0]
      const product_type: any = inputOption.product_type || productTypeOptions[0]
      const mortgage_type: any = inputOption.mortgage_type || mortgageTypeOptions[0]
      const job: any = inputOption.mortgage_type || jobsOptions[0]

      return {
        deposit,
        time_limit,
        sort,
        product_type,
        mortgage_type,
        job
      }
    }

    return {
      deposit: this.state.depositSelectedOption || depositFilterOptions[0],
      time_limit: this.state.timeSelectedOption || timeFilterOptions[0],
      sort: this.state.sortSelectedOption || sortFilterOptions[0],
      product_type: this.state.filter ? this.state.filter.product_type : null || productTypeOptions[0],
      mortgage_type: this.state.filter ? this.state.filter.mortgage_type : null || productTypeOptions[0],
      job: this.state.filter ? this.state.filter.job : null || productTypeOptions[0],
    }
  }

  /**
   * 发送搜索事件
   */
  sendSearchEvent() {
    const curCondition = {
      deposit: this.state.depositSelectedOption.value,
      time_limit: this.state.timeSelectedOption.value,
      sort: this.state.sortSelectedOption.value,
      product_type: this.state.filter['product_type'].value,
      mortgage_type: this.state.filter['mortgage_type'].value,
      job: this.state.filter.job.value
    }
    const option = {
      deposit: this.state.depositSelectedOption,
      time_limit: this.state.timeSelectedOption,
      sort: this.state.sortSelectedOption,
      product_type: this.state.filter['product_type'],
      mortgage_type: this.state.filter['mortgage_type'],
      job: this.state.filter.job
    }

    // console.log('curCondition = ', curCondition)

    // 比较过滤条件是否有变化
    if (JSON.stringify(curCondition) !== JSON.stringify(this.state.condition)) {

      this.setState({
        condition: curCondition,
        option,
      })

      // console.log('sendSearchEvent !!', curCondition)
      this.props.sendConditionAndOption(this.props.dispatchActionType, {
        condition: curCondition,
        option,
      })
    }
  }

  /**
   * 根据输入属性初始化组件的state
   * @param props 输入的属性对象
   */
  _initStateByProps(props: PageOwnProps): PageState {

    const inputOption = this._getInputOptionWithDefaultValue(props);

    const state = {
      // 贷款过滤选项
      depositFilterOptions: depositFilterOptions,
      // 贷款额度
      depositDesc: '贷款额度',
      // 贷款额度菜单是否显示
      isShowDepositMenu: false,
      // 贷款额度选项，默认选中第一个
      depositSelectedOption: inputOption.deposit,

      // 贷款期限过滤选项
      timeFilterOptions: timeFilterOptions,
      // 贷款期限
      timeDesc: '贷款期限',
      // 贷款期限菜单是否显示
      isShowTimeMenu: false,
      // 贷款期限选项，默认选中第一个
      timeSelectedOption: inputOption.time_limit,

      // 排序过滤选项
      sortFilterOptions: sortFilterOptions,
      // 贷款期限菜单是否显示
      isShowSortMenu: false,
      // 贷款期限选项，默认选中第一个
      sortSelectedOption: inputOption.sort,

      // 筛选菜单是否显示
      isShowFilterMenu: false,
      // 筛选条件对象
      filter: {
        product_type: inputOption.product_type,
        mortgage_type: inputOption.mortgage_type,
        job: inputOption.job,
      },

      // 把各个搜索条件组装成一个对象
      condition: {},

      // 菜单是否显示的标志,只要有一个菜单显示即为true
      isMenuShow: false,

      // 过滤条件数量
      filterCount: 0,
      // 是否使用过滤条件查询, 默认是false
      isFiltering: false,

      isFixTop: false,
      yOffsetHeight: 0,
    }

    return state
  }

  /**
   * 根据传入的option属性，计算新的state属性
   */
  _getNewSelectionState(inputOption: any): any {
    // const inputOption = this._getInputOptionWithDefaultValue(this.props)

    const newState = {
      // 贷款额度选项，默认选中第一个
      depositSelectedOption: inputOption.deposit || depositFilterOptions[0],
      // 贷款期限选项，默认选中第一个
      timeSelectedOption: inputOption.time_limit || timeFilterOptions[0],
      // 贷款期限选项，默认选中第一个
      sortSelectedOption: inputOption.sort || sortFilterOptions[0],
      // 筛选条件对象
      filter: {
        product_type: inputOption.product_type || productTypeOptions[0],
        mortgage_type: inputOption.mortgage_type || mortgageTypeOptions[0],
        job: inputOption.job || jobsOptions[0],
      },
    }

    return newState
  }

  /**
   * 计算组件距离顶部高度
   */
  _setInitOffsetTopHeight() {

    let query = Taro.createSelectorQuery().in(this.$scope);
    query.select('.product-filter-container').boundingClientRect();
    query.exec(res => {
      if (Array.isArray(res) && res.length > 0) {
        if (!noConsole) {
          console.log('_getInitOffsetTopHeight res = ', res)
          console.log('_getInitOffsetTopHeight = ', res[0].top)
        }

        this.setState({
          yOffsetHeight: res[0].top
        })
      }
    })
  }
}

export default ProductFilter as ComponentClass<PageOwnProps, PageState>
